package com.smile.service.impl;

import cn.dev33.satoken.spring.context.path.ApplicationContextPathLoading;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dtflys.forest.annotation.Get;
import com.dtflys.forest.annotation.Trace;

import com.smile.api.OperateLogApi;
import com.smile.api.OssApi;
import com.smile.commons.action.ActionUtils;
import com.smile.commons.file.FileUtils;
import com.smile.commons.page.MyBatisPlusPageConverter;
import com.smile.commons.page.R;
import com.smile.commons.time.TimeUtils;
import com.smile.file.uitl.MinioUtil;
import com.smile.mapper.*;
import com.smile.model.domain.*;
import com.smile.model.dto.request.*;
import com.smile.model.response.response.*;
import com.smile.request.AddOperateLogRequest;
import com.smile.service.AirportService;
import com.smile.service.DroneService;
import com.smile.service.FlightTaskProcessService;
import com.smile.service.MediaService;
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipParameters;
import org.apache.catalina.User;
import org.bouncycastle.math.raw.Mod;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Service
public class MediaServiceImpl implements MediaService {

    @Autowired
    private DroneMapper droneMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private MediaMapper mediaMapper;

    @Autowired
    private AirportMapper airportMapper;


    @Autowired
    private AirLineMapper airlineMapper;

    @Autowired
    private OssApi minioApi;
    @Autowired
    private InspectionTaskMapper inspectionTaskMapper;
    @Autowired
    private ApplicationContextPathLoading getApplicationContextPathLoading;

    @Override
    public List<GetMediaDeviceResponseDTO> getDeviceList(GetMediaDeviceRequestDTO getMediaDeviceRequestDTO) {
        Long userId = Long.valueOf(StpUtil.getLoginId().toString());
        SmilePlusUser user = userMapper.selectById(userId);
        Long organizationId = user.getOrganizationId();
        QueryWrapper<FeisuanDrone> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotNull(getMediaDeviceRequestDTO.getDeviceName())) {
            queryWrapper.like("drone_name", getMediaDeviceRequestDTO.getDeviceName());
        }
        queryWrapper.eq("organization_id", organizationId);
        queryWrapper.isNotNull("media_upload_time");
        List<FeisuanDrone> droneList = droneMapper.selectList(queryWrapper);
        List<GetMediaDeviceResponseDTO> getMediaDeviceResponseDTOList = new ArrayList<>();
        for (FeisuanDrone drone : droneList) {
            GetMediaDeviceResponseDTO getMediaDeviceResponseDTO = new GetMediaDeviceResponseDTO();
            getMediaDeviceResponseDTO.setId(drone.getId());
            getMediaDeviceResponseDTO.setDeviceName(drone.getDroneName());
            getMediaDeviceResponseDTO.setMediaUploadTime(drone.getMediaUploadTime());
            getMediaDeviceResponseDTO.setDeviceType(1);
            getMediaDeviceResponseDTOList.add(getMediaDeviceResponseDTO);
        }
        return getMediaDeviceResponseDTOList;
    }

    @Override
    public Page<GetMediaResponseDTO> getMediaDirectory(GetMediaRequestDTO getMediaRequestDTO) {
        QueryWrapper<FeisuanMedia> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("drone_id", getMediaRequestDTO.getDeviceId());
        queryWrapper.eq("parent_id", getMediaRequestDTO.getParentId());
        if (ObjectUtil.isNotEmpty(getMediaRequestDTO.getFileName())) {
            queryWrapper.like("file_name", getMediaRequestDTO.getFileName());
        }

        if (ObjectUtil.isNotEmpty(getMediaRequestDTO.getFileType())) {
            queryWrapper.like("file_type", getMediaRequestDTO.getFileType());
        }
        queryWrapper.orderByDesc("id");
        Page<FeisuanMedia> page = mediaMapper.selectPage(new Page<>(getMediaRequestDTO.getCurrentPage(), getMediaRequestDTO.getPageSize()), queryWrapper);
//        Page<GetMediaResponseDTO> getAirportListResponseDTOPage = MyBatisPlusPageConverter.convertPage(page, GetMediaResponseDTO.class);
        Page<GetMediaResponseDTO> getAirportListResponseDTOPage = MyBatisPlusPageConverter.convertPage(page, GetMediaResponseDTO.class);

        return getAirportListResponseDTOPage;
    }

    @Override
    public List<GetMediaResponseDTO> getMediaDirectoryAll(GetMediaRequestDTO getMediaRequestDTO) {
        QueryWrapper<FeisuanMedia> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("drone_id", getMediaRequestDTO.getDeviceId());
        queryWrapper.eq("parent_id", getMediaRequestDTO.getParentId());
        if (ObjectUtil.isNotEmpty(getMediaRequestDTO.getFileName())) {
            queryWrapper.like("file_name", getMediaRequestDTO.getFileName());
        }
        if (ObjectUtil.isNotEmpty(getMediaRequestDTO.getFileType())) {
            queryWrapper.like("file_type", getMediaRequestDTO.getFileType());
        }
        queryWrapper.orderByDesc("id");
        List<FeisuanMedia> list = mediaMapper.selectList(queryWrapper);
//        Page<GetMediaResponseDTO> getAirportListResponseDTOPage = MyBatisPlusPageConverter.convertPage(page, GetMediaResponseDTO.class);
        List<GetMediaResponseDTO> getAirportListResponseDTOPage = BeanUtil.copyToList(list, GetMediaResponseDTO.class);

        return getAirportListResponseDTOPage;
    }


    @Override
    public GetMediaInfoResponseDTO getMediaInfo(Long mediaId) {

        FeisuanMedia media = mediaMapper.selectById(mediaId);
        GetMediaInfoResponseDTO getMediaResponseDTO = new GetMediaInfoResponseDTO();
        if (ObjectUtil.isNotNull(media)) {
            getMediaResponseDTO.setTakeTime(media.getTakeTime());
            QueryWrapper<FeisuanInspectionTask> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("flight_id", media.getFlightId());
            queryWrapper.last("limit 1");
            FeisuanInspectionTask feisuanInspectionTask = inspectionTaskMapper.selectOne(queryWrapper);
            if (ObjectUtil.isNotNull(feisuanInspectionTask)) {
                FeisuanAirline feisuanAirline = airlineMapper.selectById(feisuanInspectionTask.getAirlineId());
                if (ObjectUtil.isNotNull(feisuanAirline)) {
                    getMediaResponseDTO.setAirlineName(feisuanAirline.getAirlineName());
                }
            }
            getMediaResponseDTO.setTaskName(media.getPlanName());
            getMediaResponseDTO.setFileName(media.getFileName());
            getMediaResponseDTO.setFileType(media.getFileType());
            getMediaResponseDTO.setFileUrl(media.getFileUrl());
            getMediaResponseDTO.setFlightId(media.getFlightId());
            getMediaResponseDTO.setSuffix(media.getSuffix());
            getMediaResponseDTO.setLatitude(media.getLatitude());
            getMediaResponseDTO.setLongitude(media.getLongitude());
            getMediaResponseDTO.setRelativeAltitude(media.getRelativeAltitude());
            getMediaResponseDTO.setAbsoluteAltitude(media.getAbsoluteAltitude());
            getMediaResponseDTO.setId(Long.valueOf(media.getId()));
            FeisuanAirport airport = airportMapper.selectById(media.getAirportId());

//            getMediaResponseDTO.
            if (ObjectUtil.isNotNull(airport)) {
                getMediaResponseDTO.setAddress(airport.getAddress());
            }
            getMediaResponseDTO.setTakeTime(media.getTakeTime());
        }
        return getMediaResponseDTO;
    }

    @Override
    public GetMediaShareResponseDTO addMediaShare(AddMediaShareRequestDTO shareRequestDTO) {
        FeisuanMediaShare feisuanMediaShare = new FeisuanMediaShare();
        feisuanMediaShare.setCreateTime(LocalDateTime.now());
        feisuanMediaShare.setFileIds(shareRequestDTO.getFileIds());
        feisuanMediaShare.setCode(shareRequestDTO.getCode());
        feisuanMediaShare.setShareUserId((Long) StpUtil.getLoginId());
        feisuanMediaShare.setIsEncrypted(shareRequestDTO.getIsEncrypted());
        feisuanMediaShare.setPassword(shareRequestDTO.getPassword());
        feisuanMediaShare.setExpiredTime(shareRequestDTO.getExpiredTime());
        GetMediaShareResponseDTO getMediaShareResponseDTO = new GetMediaShareResponseDTO();
        return getMediaShareResponseDTO;
    }

    @Override
    public Boolean updateMedia(GetMediaRequestDTO getMediaRequestDTO) {

        UpdateWrapper<FeisuanMedia> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", getMediaRequestDTO.getId());
        updateWrapper.set("file_name", getMediaRequestDTO.getFileName());
        int result = mediaMapper.update(new FeisuanMedia(), updateWrapper);
        if (result > 0) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public Boolean deleteMedia(GetMediaRequestDTO getMediaRequestDTO) {

        UpdateWrapper<FeisuanMedia> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", getMediaRequestDTO.getId());
//        updateWrapper.set("file_name",getMediaRequestDTO.getFileName());
        int result = mediaMapper.deleteById(getMediaRequestDTO);
        if (result > 0) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public Boolean batchDeleteMedia(GetMediaRequestDTO getMediaRequestDTO) {

        UpdateWrapper<FeisuanMedia> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", getMediaRequestDTO.getId());
//        updateWrapper.set("file_name",getMediaRequestDTO.getFileName());
        List<Long> ids = getMediaRequestDTO.getIds();

        for (Long id : ids) {
            int result = mediaMapper.deleteById(id);
        }
        return true;
    }

    @Override
    public String batchDownload(GetMediaRequestDTO getMediaRequestDTO) {

        UpdateWrapper<FeisuanMedia> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", getMediaRequestDTO.getId());
//        updateWrapper.set("file_name",getMediaRequestDTO.getFileName());
        List<Long> ids = getMediaRequestDTO.getIds();
        List<String> feisuanMediaList = mediaMapper.selectBatchIds(ids).stream()
                .map(FeisuanMedia::getFileUrl)
                .collect(Collectors.toList());
        ;

        String zipFileName = "compressed_" + System.currentTimeMillis() + ".zip";
        String outputPath = "file";
        String downloadDir = "file/downloads_" + System.currentTimeMillis();
        List<String> zipLst = new ArrayList<>();
        Path dirPath = Paths.get(downloadDir);
        try {
            Files.createDirectory(dirPath);

            for (String fileUrl : feisuanMediaList) {
                String fileName = fileUrl.substring(fileUrl.lastIndexOf('/') + 1);
                Path filePath = dirPath.resolve(fileName);

                try (InputStream in = new URL(fileUrl).openStream()) {
                    Files.copy(in, filePath);
                    zipLst.add(downloadDir + "/" + fileName);
                }
            }
        } catch (Exception e) {

        }
        File zipFile = new File(outputPath, zipFileName);
        try (ZipFile zip = new ZipFile(zipFile)) {
            ZipParameters parameters = new ZipParameters();
            parameters.setIncludeRootFolder(false);

            for (String file : zipLst) {
                File file1 = new File(file);
                if (file1.isDirectory()) {
                    zip.addFolder(file1, parameters);
                } else {
                    zip.addFile(file1, parameters);
                }
            }

            File file1 = new File("file/"+zipFileName);
            System.out.println("file/"+zipFileName);
            MultipartFile multipartFile = FileUtils.fileToMultipartFile(file1, "file");
            System.out.println(multipartFile.getSize());
            MinioUtil minioUtil = new MinioUtil();
            Map<String, Object> fileInfo = minioUtil.uploadFile(multipartFile,"my-bucket","zip");
            if (fileInfo != null) {
                String url = fileInfo.get("url").toString();
                return url;
            }
//            R<Map> mapR = minioApi.uploadZip(multipartFile);
//            System.out.println(mapR.getData());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return  "file/" + zipFileName;
    }

    @Override
    public String directoryDownload(GetMediaRequestDTO getMediaRequestDTO) {

        UpdateWrapper<FeisuanMedia> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", getMediaRequestDTO.getId());
        List<Long> ids = getMediaRequestDTO.getIds();
        List<String> feisuanMediaList = mediaMapper.selectBatchIds(ids).stream()
                .map(FeisuanMedia::getFileUrl)
                .collect(Collectors.toList());
        String zipFileName = "compressed_" + System.currentTimeMillis() + ".zip";
        String outputPath = "file";
        String downloadDir = "file/downloads_" + System.currentTimeMillis();
        List<String> zipLst = new ArrayList<>();
        Path dirPath = Paths.get(downloadDir);
        try {
            Files.createDirectory(dirPath);

            for (String fileUrl : feisuanMediaList) {
                String fileName = fileUrl.substring(fileUrl.lastIndexOf('/') + 1);
                Path filePath = dirPath.resolve(fileName);

                try (InputStream in = new URL(fileUrl).openStream()) {
                    Files.copy(in, filePath);
                    zipLst.add(downloadDir + "/" + fileName);
                }
            }
        } catch (Exception e) {

        }
        File zipFile = new File(outputPath, zipFileName);
        try (ZipFile zip = new ZipFile(zipFile)) {
            ZipParameters parameters = new ZipParameters();
            parameters.setIncludeRootFolder(false);

            for (String file : zipLst) {
                File file1 = new File(file);
                if (file1.isDirectory()) {
                    zip.addFolder(file1, parameters);
                } else {
                    zip.addFile(file1, parameters);
                }
            }

            File file1 = new File("file/"+zipFileName);
            System.out.println("file/"+zipFileName);
            MultipartFile multipartFile = FileUtils.fileToMultipartFile(file1, "file");
            System.out.println(multipartFile.getSize());
            MinioUtil minioUtil = new MinioUtil();
            Map<String, Object> fileInfo = minioUtil.uploadFile(multipartFile,"my-bucket","zip");
            if (fileInfo != null) {
                String url = fileInfo.get("url").toString();
                return url;
            }
//            R<Map> mapR = minioApi.uploadZip(multipartFile);
//            System.out.println(mapR.getData());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return  "file/" + zipFileName;
    }


}
